package other.xsy.baidu;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.ScheduleJob;
import com.rkhd.platform.sdk.data.model.Lead;
import com.rkhd.platform.sdk.data.model.Opportunity;
import com.rkhd.platform.sdk.data.model.SyncConfig__c;
import com.rkhd.platform.sdk.data.model.User;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.http.CommonData;
import com.rkhd.platform.sdk.http.CommonHttpClient;
import com.rkhd.platform.sdk.http.HttpResult;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.model.BatchOperateResult;
import com.rkhd.platform.sdk.model.OperateResult;
import com.rkhd.platform.sdk.model.QueryResult;
import com.rkhd.platform.sdk.param.ScheduleJobParam;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XObjectService;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.xsy.baidu.util.HCDateUtils;
import other.xsy.baidu.util.HCXObjectService;
import other.xsy.baidu.util.HcUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 同步百度营销云线索数据
 * @Author: 黎炎松
 * @Date: 2024/5/16 10:29
 */
public class SyncBdLeadDataSchedule implements ScheduleJob, FutureTask {

    private static HCXObjectService hcxObjectService = new HCXObjectService();
    public static final CommonHttpClient HTTP_CLIENT = CommonHttpClient.instance();
    protected XoqlService xoqlService = XoqlService.instance();
    private static final Logger logger = LoggerFactory.getLogger();
    private static String LOGGER_MSG = "同步百度营销云线索数据 ==> ";
    // 用户集合触发下标 用来轮询分配线索
    private int userListActIndex = 0;
    // 产品选项集
    private JSONArray productPick;
    // 省份选项集
    private JSONArray provincePick;
    // 城市选项集
    private JSONArray cityPick;
    // 请求地址
    private String reqUrl = "https://api.baidu.com/json/sms/service/LeadsNoticeService/getNoticeList";

    // 失效的百度营销账号
    private List<String> tokenExpireAccount;

    // 请求账号 token 有效期为三个月 需要到百度营销平台进行续签 （目前只用- 格创东智武汉01、格创东智武汉03 账号，其他可弃用）
    private List<Map<String, String>> accountList = Arrays.asList(
        new HashMap<String, String>(){{
            put("syncKey", "BDYX_4");
            put("userName", "格创东智武汉01");
            put("queryUserSql", "select id,name,dimDepart from user where status = 1 and assignBdAccount__c in (6) order by createdAt"); // 查询分配账号四的用户
            put("accessToken", "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhY2MiLCJhdWQiOiLmlrBDUk3nmb7luqbokKXplIDmlbDmja7lr7nmjqUiLCJ1aWQiOjU2NDg4MDIyLCJhcHBJZCI6IjZlZDM0ZWZmNGQyNzg4ZTY3OWI3ZjJiNGRjODEyOGVmIiwiaXNzIjoi5ZWG5Lia5byA5Y-R6ICF5Lit5b-DIiwicGxhdGZvcm1JZCI6IjQ5NjAzNDU5NjU5NTg1NjE3OTQiLCJleHAiOjQxMDI0MTYwMDAsImp0aSI6Ijg4MjgzOTg3MzU0MjU3NzM1OTUifQ.wWej3oHRkdWK4_s_g1j6OUl485TP-6kX21knI_wi-bJoWuFJWOhPqMWdYr-CUKpo");
        }},
        new HashMap<String, String>(){{
            put("syncKey", "BDYX_5");
            put("userName", "格创东智武汉03");
            put("queryUserSql", "select id,name,dimDepart from user where status = 1 and assignBdAccount__c in (7) order by createdAt"); // 查询分配账号五的用户
            put("accessToken", "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhY2MiLCJhdWQiOiJDUk3nmb7luqbokKXplIDmlbDmja7ojrflj5YiLCJ1aWQiOjYwMDE1MjkyLCJhcHBJZCI6Ijg0NjYxOTUwODdiYWE4ZTJiZmE3MmI3OTk5NjIxNzA3IiwiaXNzIjoi5ZWG5Lia5byA5Y-R6ICF5Lit5b-DIiwicGxhdGZvcm1JZCI6IjQ5NjAzNDU5NjU5NTg1NjE3OTQiLCJleHAiOjQxMDI0MTYwMDAsImp0aSI6IjkxNDQxNDAxOTgxNzU5NzM0MTEifQ.NAKeMStK3qDURhuMXjVrmr2J46QNvvv5IUENWLylok4SUyQ2UKh3c4YJkDAbElny");
        }},
        new HashMap<String, String>(){{
            put("syncKey", "BDYX_1");
            put("userName", "科天武汉02");
            put("queryUserSql", "select id,name,dimDepart from user where status = 1 and assignBdAccount__c in (8) order by createdAt"); // 查询分配账号一的用户
            put("accessToken", "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhY2MiLCJhdWQiOiJDUk3nmb7luqbokKXplIDmlbDmja7or7vlj5YwMiIsInVpZCI6NTgwMzM2OTAsImFwcElkIjoiMDc0ZDUyZTNhOWYwMWMzNTQwYTU4MmIyM2RkYTZiMTUiLCJpc3MiOiLllYbkuJrlvIDlj5HogIXkuK3lv4MiLCJwbGF0Zm9ybUlkIjoiNDk2MDM0NTk2NTk1ODU2MTc5NCIsImV4cCI6NDEwMjQxNjAwMCwianRpIjoiLTkwMzM2NTMyOTgzMzU2MDQ2NTYifQ.54yEDezSYw10VFUUfEYD0UzHDNIujh9YSaDdR5KAi9EEDhfocM6Z_GePFmnaFXJP");
        }},
        new HashMap<String, String>(){{
            put("syncKey", "BDYX_2");
            put("userName", "格创东智武汉04");
            put("queryUserSql", "select id,name,dimDepart from user where status = 1 and assignBdAccount__c in (9) order by createdAt"); // 查询分配账号二的用户
            put("accessToken", "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhY2MiLCJhdWQiOiJDUk3nmb7luqbokKXplIDmlbDmja7or7vlj5YiLCJ1aWQiOjY2ODMyOTYwLCJhcHBJZCI6IjYxODJmY2Y0ZDk0N2M0NmMyMzg0YTBlOWEzNjMwMGE4IiwiaXNzIjoi5ZWG5Lia5byA5Y-R6ICF5Lit5b-DIiwicGxhdGZvcm1JZCI6IjQ5NjAzNDU5NjU5NTg1NjE3OTQiLCJleHAiOjQxMDI0MTYwMDAsImp0aSI6Ii04ODI0Mjk0NjcwODE1NDIwNDE0In0.BzMZ8-Dy-FqQ56eYj02Wqhc_e2zrYg-nxYZ0PyxOh2jRmoHa5YMFYqvanB30OqeK");
        }},
        new HashMap<String, String>(){{
            put("syncKey", "BDYX_3");
            put("userName", "格创东智武汉05");
            put("queryUserSql", "select id,name,dimDepart from user where status = 1 and assignBdAccount__c in (10) order by createdAt"); // 查询分配账号三的用户
            put("accessToken", "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJhY2MiLCJhdWQiOiJDUk3nmb7luqbokKXplIDmlbDmja7or7vlj5YwNSIsInVpZCI6NjY4MzI5NTksImFwcElkIjoiZTI0NWZiYzc3M2VlYzEzYzJhYjgzNTU3OTYwMmMxZDEiLCJpc3MiOiLllYbkuJrlvIDlj5HogIXkuK3lv4MiLCJwbGF0Zm9ybUlkIjoiNDk2MDM0NTk2NTk1ODU2MTc5NCIsImV4cCI6NDEwMjQxNjAwMCwianRpIjoiLTkwOTA2MjM1NjU2MTU5Mzk1NzEifQ.XfkckaQ76QhgGKaCPkm5UAyahTt7tTR3JSYCG4_ga7Jqp52OpYXsAr7sEaz8LDk8");
        }}
    );

    // 直辖市对应的城市id
    private Map<Integer, Integer> provinceMap = new HashMap<Integer, Integer>(){{
        put(2, 2); // 北京市
        put(3, 3); // 天津市
        put(10, 74); // 上海市
        put(23, 238); // 重庆市
    }};

    // 执行定时任务
    @Override
    public void execute(ScheduleJobParam scheduleJobParam) {
        logger.info(LOGGER_MSG + " 执行定时任务开始");
        try {
            String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
            logger.info(LOGGER_MSG + "异步ID:" + messageId);
        } catch (Exception e) {
            logger.error(LOGGER_MSG + " ----- 发生异常：" + e.getMessage());
        }
    }

    // 执行异步函数
    @Override
    public void execute(String s) throws ScriptBusinessException {
        // 先同步百度营销
        startSyncBaiduData();

        // 同步官网数据 (解决自定义计划任务数量最大5个问题)
        SyncWebLeadDataSchedule syncWebLeadDataSchedule = new SyncWebLeadDataSchedule();
        syncWebLeadDataSchedule.syncWebBaiduData();
    }

    public static void main(String[] args) throws ApiEntityServiceException {
        new SyncBdLeadDataSchedule().startSyncBaiduData();
    }




    /**
     * 开始同步百度营销数据
     */
    public void startSyncBaiduData() {
        // 获取通用选项集数据
        productPick = HcUtils.getGlobalPicks("globalPick42__c"); // 产品通用集
        provincePick = HcUtils.getGlobalPicks("province"); // 省份
        cityPick = HcUtils.getGlobalPicks("city"); // 城市

        // 对三个账号进行数据同步
        tokenExpireAccount = new ArrayList<>();
        for (Map<String, String> account : accountList) {
            syncLeadDataByAccount(account);
        }

        // 如果有失效的账号则进行邮件发送 （通过监听字段值的变化触发邮件发送）
        logger.info("tokenExpireAccount ==> " + tokenExpireAccount);
        if (tokenExpireAccount.size() > 0) {
            // 获取当前时间 判断是否是白天工作日时间  9 - 18 之间发送
            int hours = Integer.parseInt(String.format("%tk", new Date()));
            if (hours < 9 || hours > 18) {
                logger.info("不满足发送时间：" + hours);
                return;
            }

            try {
                // 获取需要发送的用户
                String sql = "select id,sendBdyxEmail__c from user where sendBdyxEmail__c is not null ";
                List<User> userList = hcxObjectService.query(sql, User.class);
                if (userList.size() <= 0) {
                    return;
                }

                for (User user : userList) {
                    user.setSendBdyxEmail__c(user.getSendBdyxEmail__c() + 1);
                    user.setBdyxRenewalAccount__c(StringUtils.join(tokenExpireAccount, ";"));
                }
                logger.info("userList ==> " + userList);
                hcxObjectService.batchUpdate(userList);
            } catch (ApiEntityServiceException e) {
                logger.error("修改客户发送邮件标识异常: " + e.getMessage());
                throw new RuntimeException(e);
            }
        }

    }

    /**
     * 根据不同账号从百度营销获取销售线索数据
     * @param account
     */
    public void syncLeadDataByAccount(Map<String, String> account) {
        try {
            logger.info(LOGGER_MSG + " 开始同步数据: " + account.get("syncKey"));

            // 从数据配置表中获取数据
            String sql = "select id,lastSyncTime__c,syncAssistVal__c from syncConfig__c where syncKey__c = '" + account.get("syncKey") + "'";
            SyncConfig__c syncConfig = hcxObjectService.queryOne(sql, SyncConfig__c.class);
            logger.info(LOGGER_MSG + " syncConfig: " + syncConfig);
            if (syncConfig == null) {
                logger.info(LOGGER_MSG + " 数据配置信息不存在");
                return;
            }

            // 获取同步时间
            String startDate = syncConfig.getLastSyncTime__c();
            String endDate = HCDateUtils.dateToString(new Date(), HCDateUtils.FORMATTIME); // 同步结束时间
            // 如果为空则退回1天前 (日期范围最大支持30天)
            if (StringUtils.isBlank(startDate)) {
                startDate = HCDateUtils.getDaysBeforeString(1, HCDateUtils.FORMATTIME);
            }
            logger.info(LOGGER_MSG + " startDate: " + startDate);
            logger.info(LOGGER_MSG + " endDate: " + endDate);

            // 从百度营销获取数据
            JSONArray leadList = getBaiDuLeadData(account, startDate, endDate);
            logger.info(LOGGER_MSG + " leadList: " + leadList.size());

            // 百度营销线索数据
            if (leadList.size() <= 0) {
                // 更新数据配置表
                logger.info(LOGGER_MSG + " 没有需要保存的百度营销线索数据");
                syncConfig.setLastSyncTime__c(endDate);
                syncConfig.setLastSyncCount__c(0L);
                hcxObjectService.update(syncConfig);
                return;
            }

            // 查询分配客户数据
            QueryResult<JSONObject> xoqlQuery = xoqlService.query(account.get("queryUserSql"));
            List<JSONObject> userList = xoqlQuery.getRecords();
            logger.info(LOGGER_MSG + " userList " + userList);

            // 初始化下标 用来记录当前分配的用户下标
            String lastUserId = syncConfig.getSyncAssistVal__c();
            userListActIndex = 0;
            if (StringUtils.isNotBlank(lastUserId) && userList.size() > 1) {
                int index = userList.stream().map(v -> v.getString("id")).collect(Collectors.toList()).indexOf(lastUserId);
                userListActIndex = index != -1 ? index : 0;
            }
            logger.info(LOGGER_MSG + " lastUserId: " + lastUserId);
            logger.info(LOGGER_MSG + " userListActIndex: " + userListActIndex);

            // 获取新增集合
            List<Lead> addLeadList = new ArrayList<>();
            for (Object object : leadList) {
                JSONObject leadObj = (JSONObject) object;
                addLeadList.add(getLeadData(account, leadObj, userList));
            }

            // 批量保存
            logger.info(LOGGER_MSG + " addLeadList " + addLeadList.size());
            int isUpActIndex = 1; // 是否更新下次同步的index (如果新增数量是1且新增异常不进行更新：有的潜在客户已存在，会导致当前分配的用户没有进行分配)
            BatchOperateResult batchOperateResult = XObjectService.instance().insert(addLeadList, true, true);// 允许部分成功
            if (!batchOperateResult.getSuccess()) {

                // 允许部分成功 打印批量保存信息
                List<OperateResult> operateResults = batchOperateResult.getOperateResults();
                for (OperateResult operateResult : operateResults) {
                    logger.error(LOGGER_MSG + " batchOperateResult " + operateResult.getErrorMessage());
                }

                // 5000100: 部分成功  5000101: 全部失败
                Long code = batchOperateResult.getCode();
                logger.error(LOGGER_MSG + " 批量插入数据异常: code: " + code);
                logger.error(LOGGER_MSG + " 批量插入数据异常:" + batchOperateResult.getErrorMessage());
                // 不等于部分成功进行拦截 或者只有一条数据  全部失败
                if (code != 5000100 && addLeadList.size() > 1) {
                    return;
                } else {
                    isUpActIndex = 0;
                }
            }

            // 更新配置表信息
            syncConfig.setLastSyncTime__c(endDate);
            syncConfig.setLastSyncCount__c(Long.valueOf(addLeadList.size()));
            // 用来记录下次分配开始的用户
            if (userList.size() > 0 && isUpActIndex == 1) {
                syncConfig.setSyncAssistVal__c(userList.get(userListActIndex).getString("id"));
            }
            Boolean update = hcxObjectService.update(syncConfig);
            logger.info(LOGGER_MSG + " 更新数据同步配置: " + update);
            if (!update) {
                logger.error(LOGGER_MSG + " 更新数据同步配置异常");
                return;
            }

            logger.info(LOGGER_MSG + " 同步数据成功 " + account.get("syncKey"));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(LOGGER_MSG + " 同步异常:" + e.getMessage());
            tokenExpireAccount.add(String.format("%s:%s", account.get("userName"), e.getMessage()));
            //throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 根据类型获取百度营销不同数据
     * @param account
     * @param startDate
     * @param endDate
     * @return
     */
    public JSONArray getBaiDuLeadData(Map<String, String> account, String startDate, String endDate) {
        // 设置 body 请求体参数
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("userName", account.get("userName"));
        headerMap.put("accessToken", account.get("accessToken"));

        Map<String, String> bodyMap = new HashMap<>();
        bodyMap.put("solutionType", "form");
        bodyMap.put("startDate", startDate);
        bodyMap.put("endDate", endDate);
        bodyMap.put("pageNo", "1");
        bodyMap.put("pageSize", "5000"); // 最大为5000

        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("header", headerMap);
        paramsMap.put("body", bodyMap);

        JSONArray leadList = new JSONArray();

        // 需要查询的类型 form phone callback
        String[] typeArray = {"form", "phone", "callback"};
        for (String type : typeArray) {
            bodyMap.put("solutionType", type);
            paramsMap.put("body", bodyMap);
            leadList.addAll(getBaiDuData(paramsMap, account.get("userName")));
        }
        return leadList;
    }


    /**
     * 获取销售线索数据
     *
     * @param account
     * @param leadObj
     * @param userList
     * @return
     */
    public Lead getLeadData(Map<String, String> account, JSONObject leadObj, List<JSONObject> userList) {
        Lead lead = new Lead();
        lead.setEntityType(11010001100001L); // 业务类型
        lead.setDataSource__c(2); // 1:系统 2：百度营销
        lead.setName("待定"); // 名称
        lead.setCompanyName("待定"); // 公司名称
        lead.setProfession__c(36); // 行业 默认：待定
        lead.setSubsectors__c(97); // 子行业 默认：待定
        lead.setStatus(1); // 潜在客户状态 默认: 未处理
        lead.setCustomerSource__c(1); // 潜在客户来源： 默认: SEM
        lead.setSourceLevel2__c(1); // 潜在客户来源二级 默认：百度
        lead.setCountry__c(45); // 国家/地区  默认：中国
        lead.setFState(39); // 省份 默认待定
        lead.setFCity(1); // 城市 默认待定
        //lead.setDimDepart(3212422568873310L); // 所属部门 默认：市场部 （不需要赋值，系统会根据 【所有人】自动赋值）
        lead.setSyncDataId__c(leadObj.getString("clueId")); // 百度营销id
        lead.setSyncDataType__c(leadObj.getString("solutionType")); // 百度营销数据类型
        lead.setMobile(leadObj.getString("cluePhoneNumber")); // 手机
        lead.setKeyword__c(leadObj.getString("keyword")); // 关键词
        lead.setSearchterms__c(leadObj.getString("searchWord")); // 搜索词
        lead.setDeliveryUnit__c(leadObj.getString("adgroupName")); // 投放单元

        // 获取姓名 公司名称
        JSONArray formDetail = leadObj.getJSONArray("formDetail");
        if (formDetail != null) {
            for (Object form : formDetail) {
                JSONObject formObj = (JSONObject) form;
                String name = formObj.getString("name");
                String type = formObj.getString("type");
                String value = formObj.getString("value");
                if (type.equals("name")) {
                    lead.setName(value);
                } else if (name.indexOf("公司") != -1) {
                    lead.setCompanyName(value);
                }
            }
        }

        // 产品 （投放计划  3.6 QMS PC）
        String campaignName = leadObj.getString("campaignName");
        lead.setDeliveryPlan__c(campaignName); // 投放计划
        if (StringUtils.isNotBlank(campaignName)) {
            String[] camSplit = campaignName.split(" ");
            if (camSplit.length > 2) {
                lead.setProduct__c(HcUtils.getGeneralValue(productPick, camSplit[1]));
            }
        }

        // 所有人
        if (userList.size() > 0) {
            // 轮询分配给指定部门下的客户
            lead.setOwnerId(userList.get(userListActIndex).getLong("id"));
            // 判断下标是否需要重置为0
            userListActIndex++;
            if (userListActIndex == userList.size()) {
                userListActIndex = 0;
            }
        } else {
            // 如果查询不到分配用户数据，默认给到当前用户
            lead.setOwnerId(3294456680602270L);
        }

        // 省 城市
        String area = leadObj.getString("area");
        if (StringUtils.isNotBlank(area) && !Objects.equals(area, "-")) {
            String[] split = area.split("\n");
            if (split.length > 1) {
                lead.setFCity(getCityValue(cityPick, split[1].trim())); // 市
            }
            Integer province = getCityValue(provincePick, split[0].trim());
            lead.setFState(province); // 省

            // 如果是  北京市、天津市、上海市、重庆市需要特殊处理
            if (split.length == 1 && provinceMap.containsKey(province)) {
                lead.setFCity(provinceMap.get(province)); // 市
            }

        }
        logger.info(LOGGER_MSG + " lead: " + lead);
        return lead;
    }

    /**
     * 获取省份或者城市
     * @param provinceArray
     * @param Label
     * @return
     */
    public static Integer getCityValue(JSONArray provinceArray, String Label) {
        if (StringUtils.isBlank(Label)) {
            return null;
        }
        Integer value = null;
        for (Object o : provinceArray) {
            JSONObject faultJson = (JSONObject) o;
            String optionLabel = faultJson.getString("optionLabel");
            if (optionLabel.indexOf(Label) != -1)  {
                value = faultJson.getInteger("optionCode");
                break;
            }
        }
        return value;
    }

    /**
     * 获取百度营销线索数据
     * @param paramsMap
     * @return
     */
    public JSONArray getBaiDuData(Map paramsMap, String userName) {
        logger.info(userName + " 发送请求 ==> paramsMap: " + paramsMap);
        JSONArray leadList = new JSONArray();

        // 发送请求
        CommonData build = CommonData.newBuilder().callString(reqUrl)
                .callType("POST")
                .body(JSONObject.toJSONString(paramsMap))
                .formType("application/json")
                .build();
        HttpResult execute = HTTP_CLIENT.execute(build);

        // 获取数据
        String result = execute.getResult();
        if (StringUtils.isBlank(result)) {
            return leadList;
        }

        JSONObject jsonObject = JSONObject.parseObject(result);
        JSONObject header = jsonObject.getJSONObject("header");
        // 0:成功，1:部分失败，2:全部失败，3:系统错误
        Integer status = header.getInteger("status");
        if (status != 0) {
            System.out.println("status = " + status);
            // 获取异常信息
            JSONArray failuresArray = header.getJSONArray("failures");
            String message = failuresArray.stream().map(v -> {
                JSONObject fail = (JSONObject) v;
                return fail.getString("message");
            }).collect(Collectors.joining(","));
            logger.error(userName + " 发送请求 ==> 获取百度营销数据异常: " + message);

            // 如果是token过期，需要发送邮件到管理员进行通知续期
            tokenExpireAccount.add(String.format("%s:%s", userName, message));

            throw new RuntimeException(message);
            //return leadList;
        }

        JSONArray jsonArray = jsonObject.getJSONObject("body").getJSONArray("data");
        if (jsonArray == null || jsonArray.size() <= 0) {
            logger.error(userName + " 发送请求 ==> 获取百度营销数据为空");
            return leadList;
        }

        JSONObject leadData = (JSONObject) jsonArray.get(0);
        leadList = leadData.getJSONArray("noticeDetailList");
        //Integer totalNum = leadData.getInteger("totalNum");
        //System.out.println("totalNum = " + totalNum);
        //System.out.println("leadList = " + leadList.size());
        return leadList;
    }




}
